﻿using KWT.DRG_DIP.API.Infrastructure;
using KWT.DRG_DIP.Common;
using KWT.DRG_DIP.DO.System;
using KWT.DRG_DIP.DTO.User;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using static KWT.DRG_DIP.DO.System.AppSettings;
using ZXing;
using KWT.DRG_DIP.DB;
using KWT.DRG_DIP.PO.Basic;

namespace KWT.DRG_DIP.API.Controllers.Basic
{
    /// <summary>
    /// 系统
    /// </summary>
    [ApiExplorerSettings(GroupName = "basic")]
    public class SysController : BasicControllerBase
    {
        public MainEFContext main { get; set; }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public IActionResult Login(InLogin dto)
        {
            string de_acc = _Security.Rsa.Decrypt(dto.account);
            string de_pwd = _Security.Rsa.Decrypt(dto.pwd);
            //int fail_count = Convert.ToInt32(RedisHelper.Get(de_acc));
            //if (fail_count >= 3)
            //{
            //    return (false, "密码重试次数过多，请稍后再试!", null);
            //}
            if (!ef.Set<Sys_User>().Any(x => x.LoginName == de_acc))
            {
                return Fail("用户名不存在!");
            }
            Sys_User user = main.Set<Sys_User>().SingleOrDefault(x => x.LoginName.Equals(de_acc));
            string salt_pwd = _Security.Salt.Encrypt(de_pwd, user.Salt);
            if (user.Status == 0)
            {
                return Fail("账户已被禁用!");
            }
            if (!salt_pwd.Equals(user.Pwd))
            {
                //RedisHelper.IncrBy(de_acc);
                //RedisHelper.Expire(de_acc, 30);
                return Fail("密码错误!");
            }
            var tanent = main.Find<Sys_Tenant>(user.TenantID);
            var jwt = jwtSvc.Create(user, tanent.UsePolicy);
            return Output(true, "登录成功", "登录失败", new
            {
                status = true,
                access_token = jwt.access_token.Token,
                expires_in = AppSettings.JWT.AccessTokenExpires,
                refresh_token = jwt.refresh_token.Token,
                tenant_id = user.TenantID,
                role_id = user.RoleID,
                policy = tanent.UsePolicy
            });
        }

        /// <summary>
        /// 刷新access_token
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        public IActionResult Refresh(InRefresh dto)
        {
            var refresh = ef.Set<Sys_RefreshToken>().SingleOrDefault(x => x.Access_Token == dto.AccessToken);
            if (refresh == null)
            {
                return Fail("令牌不存在！");
            }
            var handler = new JwtSecurityTokenHandler();
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSettings.JWT.SecurityKey));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            bool isCan = handler.CanReadToken(refresh.Token);
            if (!isCan)
                return Fail("令牌格式错误！");

            var validateParameter = new TokenValidationParameters()
            {
                ValidateAudience = false,
                ValidateIssuer = false,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = key
            };

            SecurityToken validatedToken;
            try
            {
                handler.ValidateToken(refresh.Token, validateParameter, out validatedToken);
            }
            catch (SecurityTokenException)
            {
                return Fail("令牌验证失败！");
            }

            var jwtToken = validatedToken as JwtSecurityToken;

            var refreshToken = new JwtSecurityToken(
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddDays(AppSettings.JWT.RefreshTokenExpires),
                claims: jwtToken.Claims,
                signingCredentials: credentials
            );


            var accessToken = new JwtSecurityToken(
                    notBefore: DateTime.Now,
                    expires: DateTime.Now.AddDays(AppSettings.JWT.AccessTokenExpires),
                    claims: jwtToken.Claims.Where(x => x.Type != "role"),
                    signingCredentials: credentials
                );

            var refresh_token = handler.WriteToken(refreshToken);
            var access_token = handler.WriteToken(accessToken);

            return Output(true, "令牌刷新成功", "令牌刷新失败", access_token);
        }

        /// <summary>
        /// 当前用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public OutputResult UserInfo()
        {
            var user = CurrentUser;
            return Output(user != null, "", "", user);
        }
    }
}
